/*
 * File.h
 *
 *  Created on: Mar 25, 2010
 *      Author: Lukasz Spintzyk
 */

#ifndef FILE_H_
#define FILE_H_

#include "ph.h"

#ifndef INODE_H_
#include "Inode.h"
#endif

class InodeManager;
class BlockManager;
class BlocksNumCache;


class File
{
public:
    File(const std::string& path,
    	 InodePtr fileInode,
    	 InodeManager& inodeMgr,
    	 BlockManager& blockMgr);
    ~File();
	File(const File& file);

    uint32_t read(char *buf, size_t size, off_t offset);
    uint32_t write(const char *buf, size_t size, off_t offset);


    InodePtr d_fileInode;
    std::string name;

private:
    size_t normalizeSizePossibleToRead(size_t size, off_t offset);
    uint32_t copyFirstBlock(char* buf, size_t size,off_t offset);
    uint32_t copyInternalBlocks(char* buf, size_t size,off_t offset);
    uint32_t copyLastBlock(char* buf, size_t size,off_t offset);

    uint32_t allocateBlocksIfNeeded(size_t size, off_t offset);
    uint32_t writeToFirstBlock(const char* buf, size_t size,off_t offset);
    uint32_t writeToInternalBlocks(const char* buf, size_t size,off_t offset);
    uint32_t writeToLastBlock(const char* buf, size_t size,off_t offset);
    uint32_t writeRestOfBlock(const char* dest_buf,
				uint32_t src_block_index,
				uint32_t block_offset,
				uint32_t bytes_num_to_copy);

    uint32_t writeFullBlocks(const char* dest_buf,
				uint32_t src_block_index,
				uint32_t blocks_num_to_copy);


    uint32_t copyRestOfBlock(char* dest_buf, uint32_t src_block_index, uint32_t block_offset, uint32_t bytes_num_to_copy);
    uint32_t copyFullBlocks(char* dest_buf, uint32_t src_block_index, uint32_t blocks_num_to_copy);

	InodeManager& d_inodeMgr;
	BlockManager& d_blockMgr;
	BlocksNumCache* d_blocksCache;
    byte* d_buffer;
};

typedef boost::shared_ptr<File> FilePtr;

#endif /* FILE_H_ */
